package org.example.study7;
/**阻塞队列实现生产者消费者模型
生产消息的应用程序把消息写入消息队列(生产者)
使用消息的应用程序从消息队列中取出消息(消费者)
**/


/**
 *
 1.定义一个阻塞队列，保存消息
 2.定义生产者线程，向队列中写入数据
 3.定义一个消费者线程，从队列中取出数据
 **/
import java.util.concurrent.TimeUnit;


public class Demo_703 {
    public static void main(String[] args) {
        // 定义一个阻塞队列, 创建容量为100的自定义阻塞队列，作为生产者-消费者的共享数据容器，交易场所
        MyBlockingQueue queue = new MyBlockingQueue(100);

        // 创建生产者线程
        Thread producer = new Thread(() -> {
            int num = 0;
            // 使用循环不停的向队列中添加元素，直到队列容量占满
            while (true) {
                try {
                    // 添加元素
                    queue.put(num);// 将元素放入队列（若队列满则阻塞）
                    System.out.println("生产了元素：" + num);
                    num++;
                    // 休眠一会
                    TimeUnit.MILLISECONDS.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        // 启动生产者线程
        producer.start();

        // 定义一个消费者线程
        Thread consumer = new Thread(() -> {
            // 不断的从队列中取出元素
            while (true) {
                try {
                    // 取元素
                    Integer value = queue.take();// 从队列取出元素（若队列空则阻塞）
                    System.out.println("消费了元素：" + value);
                    // 休眠一会
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        // 启动消费者线程
        consumer.start();
    }
}

/*代码核心知识点
1. 生产者-消费者模型:
生产者线程 (producer): 不断生成数据（此处为递增整数）并存入队列。
消费者线程 (consumer): 不断从队列中取出数据并处理。
共享资源 (MyBlockingQueue): 线程安全的阻塞队列，协调生产与消费速度差异。

2. 阻塞队列的作用:
流量控制: 队列容量为100，当队列满时，生产者线程会被阻塞，直到消费者消费数据腾出空间。
线程协调: 当队列空时，消费者线程会被阻塞，直到生产者添加新数据。
解耦生产与消费逻辑: 生产者和消费者无需直接依赖彼此，只通过队列交互。

3.速度差异设计（利用休眠使生产者生产快一点消费者慢一点）:
生产者每 10ms 生产一个元素（速度快）。
消费者每 1秒 消费一个元素（速度慢）。
通过速度差异模拟实际场景中生产与消费的不平衡。*/


/*解决的问题与作用
资源竞争避免: 通过阻塞队列保证生产者和消费者的线程安全。
系统稳定性: 队列容量限制防止内存溢出（如生产者过快导致数据堆积）。
异步处理: 生产者和消费者可以独立运行，无需等待对方完成操作。
削峰填谷: 在高并发场景中缓冲突发流量（如秒杀系统中的请求队列）。
*/


/*现象与执行结果
1. 初始阶段:
生产者快速生产元素（10ms/个），队列逐渐被填满。
消费者每1秒消费一个元素，输出类似：

生产了元素：0
生产了元素：1
...
消费了元素：2
生产了元素：100
...


2. 队列满时:
当队列填满100个元素后，生产者调用 queue.put() 会被阻塞，停止生产。
消费者每消费一个元素，生产者才能继续生产一个。

3. 队列空时:
若队列被消费空（极端情况），消费者调用 queue.take() 会被阻塞，直到生产者添加新元素。*/


/*注意事项
死锁风险: 若生产者和消费者因异常未唤醒对方，需设计超时机制。
资源泄漏: 需监控队列积压情况，避免长期阻塞导致系统不可用。
性能调优: 根据实际场景调整队列容量和生产/消费速度比例。*/